package com.yanyu.space.common.im.server;

import com.yanyu.space.common.im.handler.WebSocketServerInitializer;
import com.yanyu.space.common.im.support.ImRecer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.Ordered;

import java.util.List;

/**
 * @author yanyu
 */
@Slf4j
@AllArgsConstructor
public class NettyServer implements CommandLineRunner, Ordered {

    private List<ImRecer> imRecers;
    private Integer port;

    public void start() {
        //创建事件线程组，
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        //创建服务启动器
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        try {
            //给服务启动器配置参数
            serverBootstrap.group(boosGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // 标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度。主要是作用于boss线程，用于处理新连接
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    // 禁用nagle算法,减小延迟
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childOption(ChannelOption.SO_RCVBUF, 128 * 1024)
                    .childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
                    .childHandler(new WebSocketServerInitializer(imRecers));
            //绑定端口,这里用到的是ChannelFuture类
            ChannelFuture future = serverBootstrap.bind(port).sync();
            //关闭通道
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //在这里关闭事件线程组,释放资源
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    @Override
    public void run(String... args) throws Exception {
        new Thread(() -> {
            start();
        }).start();
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE + 2;
    }
}
